# -*- coding: utf-8 -*-

import os

from hlm.node import *

from ip.hana import NodeHana
from ip.fabrics import *

from mtl.hw_defs import VARS
from uut.op_dispatcher import NodeOpDispatcher
from uut.main_memory import NodeMainMemory


class Glb:
    mem_cas_letency = 2
    mem_elements = 8388608

    sm_size = VARS.alu_offset * VARS.num_of_alu

    filename = 'opcf'
    compile = True

    visual = False


class DesignUnitTest(TopModule):
    def initialize(self, params: ObjectDict) -> None:
        # Find the program folder.
        program_dir = os.path.join(os.path.dirname(__file__), '..', 'programs')
        program_dir = os.path.abspath(program_dir)
        # Based on the filename, combine the file path.
        filepath = os.path.join(program_dir, Glb.filename, Glb.filename)
        # Construct the driver nodes.
        self.node.op_dispatcher = self.node_create(
            NodeOpDispatcher,
            {'compile': Glb.compile,
             'filepath': filepath,
             'visual': Glb.visual})

        self.node.main_memory = self.node_create(
            NodeMainMemory,
            {'cas': Glb.mem_cas_letency,
             'multiplexer': VARS.multiplexer,
             'size': Glb.mem_elements})

        self.node.chip = self.node_create(
            NodeHana,
            {'multiplexer': VARS.multiplexer,
             'peer_id_base': 0,
             'num_of_peer_group': 4,
             'num_of_peer': 4,
             'softmem_size': Glb.sm_size,
             'num_of_main_memory': 1,
             'num_of_alu': VARS.num_of_alu,
             'total_peers': 16,
             'base_ptrs': [(ii * VARS.alu_offset) for ii in range(VARS.num_of_alu)]})

        # Preload the main memory.
        self.node.main_memory.preload(self.node.op_dispatcher.aops())

        # Bypass the halt interrupt.
        self.port.halt_int = self.port_in_direct(bool)
        self.node.chip.port.halt.connect(self.port.halt_int)

        # Connect the ports.
        ChannelTranOpFabric.connect(self.node.op_dispatcher.port.top_sender,
                                    self.node.chip.port.top_receiver)
        ChannelExecOpFabric.connect(self.node.op_dispatcher.port.eop_sender,
                                    self.node.chip.port.eop_receiver)
        ChannelLoadReqFabric.connect(self.node.chip.port.memory_requester[0],
                                     self.node.main_memory.port.request_receiver)
        ChannelLoadFabric.connect(self.node.main_memory.port.load_sender,
                                  self.node.chip.port.memory_receivers[0])
        ChannelStoreFabric.connect(self.node.chip.port.memory_senders[0],
                                   self.node.main_memory.port.store_receiver)
